package main

import (
	"io"
	_ "net/http/pprof"
	"os"
	"web_framework/config"
	"web_framework/router"
	"web_framework/storage"
	"web_framework/websocket/v1/router"

	"github.com/gin-gonic/gin"
	"github.com/pkg/errors"
	log "github.com/sirupsen/logrus"
	"github.com/spf13/pflag"
	"time"
)

var (
	cfg     = pflag.StringP("config", "c", "", "apiserver config file path.")
	version = pflag.BoolP("version", "v", false, "show version info.")
)

var tasks = []func() error{
	setLogLevel,
	setRedisPool,
	setMySQLConnection,
	//runDatabaseMigrations,
	//setRootAccount,
	setRouter,
	startRouteWebsock,
	setAPIs,
	startServer,
}

func main() {
	//设置时区
	time.Local,_  = time.LoadLocation("Asia/Shanghai")
	// init config
	if err := config.Init(*cfg); err != nil {
		panic(err)
	}

	// start services
	start()

}

func start() error {
	log.Infoln("Service start")

	for _, t := range tasks {
		if err := t(); err != nil {
			log.Fatal(err)
		}
	}

	return nil
}

func setLogLevel() error {
	if config.C.Log.LoggerType == "json" {
		log.SetFormatter(&log.JSONFormatter{})
	} else {

		log.SetFormatter(&log.TextFormatter{})
	}
	log.SetOutput(os.Stdout)
	log.SetLevel(log.Level(config.C.Log.LoggerLevel))

	return nil
}

func setRedisPool() error {
	log.WithField("url", config.C.Redis.URL).Info("setup redis connection pool")
	err := storage.InitRedisPool(config.C.Redis.URL)
	return err
}

func setMySQLConnection() error {
	log.WithField("DB type", config.C.DB.Type).WithField("dsn", config.C.DB.DSN).Info("connecting to DB")
	db, err := storage.OpenDatabase(config.C.DB.Type, config.C.DB.DSN)
	if err != nil {
		return errors.Wrap(err, "database connection error")
	}
	config.C.DB.DB = db
	return nil
}

func setRouter() error {
	if config.C.RunMode == "DEBUG" {
		gin.SetMode(gin.DebugMode)
	} else {
		gin.SetMode(gin.ReleaseMode)
	}

	gin.DisableConsoleColor()

	// Logging to a file.
	if config.C.Log.LoggerFile != "" {
		f, _ := os.Create(config.C.Log.LoggerFile)
		gin.DefaultWriter = io.MultiWriter(f, os.Stdout)
	} else {
		gin.DefaultWriter = io.MultiWriter(os.Stdout)
	}

	config.C.Router = gin.New()
	config.C.Router.Use(gin.Recovery())

	return nil
}

func setAPIs() error {
	api.BindAPIs()
	return nil
}

func startServer() error {
	config.C.Router.Run(config.C.Address)

	// go func() {
	// 	config.C.Router.Run(config.C.Address)
	// }()
	return nil
}

func startRouteWebsock() error {
	config.C.Router.GET("/api/v1/ws", router.WsHand)
	// http.HandleFunc("/ws", router.WsHand)
	// err := http.ListenAndServe(":8080", nil)
	// if err != nil {
	// 	log.Fatal("ListenAndServe", err.Error())
	// }

	return nil
}
